﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ProviderFactory.cs" company="">
//   
// </copyright>
// <summary>
//   The provider factory.
// </summary>
// --------------------------------------------------------------------------------------------------------------------


using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
using Microsoft.Office.Interop.Excel;
using Systemathics.FrameWork.Interfaces;
using Application = Microsoft.Office.Interop.Excel.Application;


namespace Systemathics.FrameWork
{
    public static class ProviderFactory
    {
        public static Boolean GetInstruments(String excelFile, String Tag,  ref List<String> InstrumentsName)
        {
            Thread.CurrentThread.CurrentCulture = GlobalVariables.SystemathicsCulture();

            var file = GlobalVariables.PARAMETERS + "\\" + excelFile;
            if (!File.Exists(file))
            {
                new RemotingLogClient().Trace(new FireMessageEventArgs(excelFile + " Parameters File doesn't exists To Load Insrtuments Names", Time.Now.TimeOfDay));
                return false;
            }

            var app = new Application();
            var workbooks = app.Workbooks;
            var workbook = workbooks.Open(file, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
            var w = (Worksheet)workbook.Sheets["Instruments"];

            if (w != null)
            {
                Range excelRange = w.UsedRange;
                var valueArray = (object[,])excelRange.get_Value(XlRangeValueDataType.xlRangeValueDefault);
                var rowCount = valueArray.GetLength(0);

                for (int rowIndex = 2; rowIndex <= rowCount; rowIndex++)
                    if (valueArray[rowIndex, 1] != null)
                        if (valueArray[rowIndex, 1].ToString() == Tag && valueArray[rowIndex, 2] != null)
                            InstrumentsName.Add(valueArray[rowIndex, 2].ToString());

                workbook.Close(null, null, null);
                app.Workbooks.Close();
                app.Quit();
                Marshal.ReleaseComObject(excelRange);
                Marshal.ReleaseComObject(w);
                Marshal.ReleaseComObject(workbook);
                Marshal.ReleaseComObject(workbooks);
                Marshal.ReleaseComObject(app);

                if (InstrumentsName.Count > 0)
                    return true;
                new RemotingLogClient().Trace(new FireMessageEventArgs(excelFile + " No Instruments NAme present in " + excelFile, Time.Now.TimeOfDay));
            }
            return false;
        }
        public static Boolean GetParameters(Parameters attribute, StrategyCell cell, ref Dictionary<String, Dictionary<String, Object>> @params)
        {
            if (attribute != null)
            {
                Thread.CurrentThread.CurrentCulture = GlobalVariables.SystemathicsCulture();
                var excelFile = attribute.Name;

                if (excelFile == null)
                    return true;

                var file = GlobalVariables.PARAMETERS + "\\" + excelFile;
                if (!File.Exists(file))
                {
                    new RemotingLogClient().Trace(new FireMessageEventArgs(excelFile + " Parameters File doesn't exists", Time.Now.TimeOfDay));
                    return false;
                }

                @params = new Dictionary<string, Dictionary<string, object>>();
                var app = new Application();
                var workbooks = app.Workbooks;
                var workbook = workbooks.Open(file, Type.Missing, Type.Missing, Type.Missing, Type.Missing,Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
                var w = (Worksheet) workbook.Sheets["Parameters"];

                if(w != null)
                {
                    Range excelRange = w.UsedRange;
                    var valueArray = (object[,])excelRange.get_Value(XlRangeValueDataType.xlRangeValueDefault);
                    var rowCount = valueArray.GetLength(0);
                    var columnCount = valueArray.GetLength(1);

                    for (int rowIndex = 2; rowIndex <= rowCount; rowIndex++)
                    {
                        if (valueArray[rowIndex, 1] != null)
                        {
                            if (valueArray[rowIndex, 1].ToString() == cell.Info)
                            {
                                var instrumentName = valueArray[rowIndex, 2].ToString();
                                @params[instrumentName] = new Dictionary<string, object>();
                                for (int colIndex = 3; colIndex <= columnCount; colIndex++)
                                {
                                    if (valueArray[1, colIndex] != null)
                                    {
                                        var paramName = valueArray[1, colIndex].ToString();
                                        if (valueArray[rowIndex, colIndex].GetType() == typeof(double))
                                            @params[instrumentName].Add(paramName,
                                                                       new decimal((double)valueArray[rowIndex, colIndex]));
                                        else if (valueArray[rowIndex, colIndex].GetType() == typeof(string))
                                            @params[instrumentName].Add(paramName, valueArray[rowIndex, colIndex]);
                                    }
                                }
                            }
                        }
                    }
                    workbook.Close(null, null, null);
                    app.Workbooks.Close();
                    app.Quit();
                    Marshal.ReleaseComObject(excelRange);
                    Marshal.ReleaseComObject(w);
                    Marshal.ReleaseComObject(workbook);
                    Marshal.ReleaseComObject(workbooks);
                    Marshal.ReleaseComObject(app);
                    return true;
                }
                if (@params.Count == 0)
                {
                    new RemotingLogClient().Trace(new FireMessageEventArgs(" 0 Parameters found for :" + excelFile,Time.Now.TimeOfDay));
                    new RemotingLogClient().Trace(new FireMessageEventArgs(" Check 'Info' Column of: " + excelFile,Time.Now.TimeOfDay));
                    return false;
                }
            }
            else
            {
                new RemotingLogClient().Trace(new FireMessageEventArgs(cell.Name + " :No Attribute Parameters detected for " + cell.Info,Time.Now.TimeOfDay));
                return true;
            }
            return false;
        }
        public static Pattern[] GetStrategiesPattern(string path)
        {
            var directory = new DirectoryInfo(path);
            var o = new List<Pattern>();
            foreach (var file in directory.GetFiles("*.dll"))
            {
                var a = Assembly.Load(AssemblyName.GetAssemblyName(file.FullName));
                var type = a.GetTypes()[0];
                var attributes = Attribute.GetCustomAttributes(type);

                foreach (Attribute att in attributes)
                    if (att.GetType() == typeof(Pattern))
                        o.Add((Pattern)att);
            }
            return o.ToArray();
        }
        public static Form GetGui(GUI gui, string path)
        {
            var directory = new DirectoryInfo(path);
            try
            {
                foreach (var file in directory.GetFiles("*.exe"))
                {
                    var assembly = Assembly.Load(AssemblyName.GetAssemblyName(file.FullName));
                    foreach (var u in assembly.GetTypes())
                    {
                        var attributes = Attribute.GetCustomAttributes(u);

                        foreach (var att in attributes)
                        {
                            if (att.GetType() == typeof (GUI)) 
                            {
                                var p = (GUI) att;
                                if (p.Name == gui.Name && p.Version == gui.Version)
                                {
                                    var types = assembly.GetTypes();
                                    foreach (Type type in types)
                                        if (type.IsSubclassOf(typeof (Form)))
                                            return assembly.CreateInstance(type.ToString()) as Form;
                                }
                            }
                        }
                    }
                }
            }
            catch (ReflectionTypeLoadException)
            {
            }

            return null;
        }
        public static IDataProvider GetDataProvider(string dataProviderName, string path)
        {
            var directory = new DirectoryInfo(path);
            foreach (var file in directory.GetFiles("*.dll"))
            {
                try
                {
                    var assembly = Assembly.Load(AssemblyName.GetAssemblyName(file.FullName));
                    var types = assembly.GetTypes();
                    foreach (var type in types)
                    {
                        if (type.GetInterface("IDataProvider") != null)
                        {
                            var attribute = Attribute.GetCustomAttribute(type, typeof(ProviderName)) as ProviderName;
                            if (attribute.Name == dataProviderName)
                                return assembly.CreateInstance(type.ToString()) as IDataProvider;
                        }
                    }
                }
                catch (ReflectionTypeLoadException)
                {
                }
            }
            return null;
        }
        public static IOrderProvider GetOrderProvider(string orderProviderName, string Path)
        {
            var directory = new DirectoryInfo(Path);
            foreach (var file in directory.GetFiles("*.dll"))
            {
                try
                {
                    var assembly = Assembly.Load(AssemblyName.GetAssemblyName(file.FullName));
                    var types = assembly.GetTypes();
                    foreach (var type in types)
                    {
                        if (type.GetInterface("IOrderProvider") != null)
                        {
                            var attribute = Attribute.GetCustomAttribute(type, typeof(ProviderName)) as ProviderName;
                            if (attribute.Name == orderProviderName)
                                return assembly.CreateInstance(type.ToString()) as IOrderProvider;
                        }
                    }
                }
                catch (ReflectionTypeLoadException)
                {
                }
            }
            return null;
        }
        public static IFees GetFeesProvider(string feesproviderName, string Path)
        {
            var directory = new DirectoryInfo(Path);
            foreach (var file in directory.GetFiles("*.dll"))
            {
                try
                {
                    var assembly = Assembly.Load(AssemblyName.GetAssemblyName(file.FullName));
                    var types = assembly.GetTypes();
                    foreach (Type type in types)
                    {
                        if (type.GetInterface("IFees") != null)
                        {
                            var attribute = Attribute.GetCustomAttribute(type, typeof(BrokerFees)) as BrokerFees;
                            if (attribute.Name == feesproviderName)
                                return assembly.CreateInstance(type.ToString()) as IFees;
                        }
                    }
                }
                catch (ReflectionTypeLoadException)
                {
                }
            }
            return null;
        }
        public static IOrderProvider GetVirtualOrderProvider(DataService dataService, string path)
        {
            var directory = new DirectoryInfo(path);

            foreach (var file in directory.GetFiles("*.dll"))
            {
                try
                {
                    var assembly = Assembly.Load(AssemblyName.GetAssemblyName(file.FullName));
                    var types = assembly.GetTypes();
                    foreach (var type in types)
                    {
                        if (type.GetInterface("IDataProvider") == null && type.GetInterface("IOrderProvider") != null)
                        {
                            var attribute = Attribute.GetCustomAttribute(type, typeof(ProviderName)) as ProviderName;
                            if (attribute.Name == StrategyMode.Virtual.ToString())
                                return assembly.CreateInstance(type.ToString(), true, BindingFlags.Default, null, new object[] { dataService }, CultureInfo.CurrentCulture, null) as IOrderProvider;
                        }
                    }
                }
                catch (Exception ex)
                {
                    new RemotingLogClient().Trace(new FireMessageEventArgs(ex, DateTime.Now.TimeOfDay));
                }
            }

            return null;
        }
        public static object GetMixedProvider(string mixedProviderName, string path)
        {
            var directory = new DirectoryInfo(path);
            try
            {
                foreach (var file in directory.GetFiles("*.dll"))
                {
                    var assembly = Assembly.Load(AssemblyName.GetAssemblyName(file.FullName));
                    var types = assembly.GetTypes();
                    foreach (var type in types)
                    {
                        if (type.GetInterface("IDataProvider") != null && type.GetInterface("IOrderProvider") != null)
                        {

                            var attribute = Attribute.GetCustomAttribute(type,typeof(ProviderName)) as ProviderName;
                            if (attribute.Name == mixedProviderName)
                                return assembly.CreateInstance(type.ToString()); 
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                new RemotingLogClient().Trace(new FireMessageEventArgs(ex,DateTime.Now.TimeOfDay));
            }
            return null;
        }
        public static List<string> GetDataProvidersName(string path)
        {
            var directory = new DirectoryInfo(path);
            var listOfmdp = new List<string>();

            foreach (var file in directory.GetFiles("*.dll"))
            {
                try
                {
                    var assembly = Assembly.Load(AssemblyName.GetAssemblyName(file.FullName));
                    var Types = assembly.GetTypes();
                    foreach (var type in Types)
                    {
                        if (type.GetInterface("IDataProvider") != null && type.GetInterface("IOrderProvider") == null)
                        {
                            var attribute = Attribute.GetCustomAttribute(type, typeof(ProviderName)) as ProviderName;
                            listOfmdp.Add(attribute.Name);
                        }
                    }
                }
                catch (Exception ex)
                {
                    new RemotingLogClient().Trace(new FireMessageEventArgs(ex, DateTime.Now.TimeOfDay));
                }
            }
            return listOfmdp;
        }
        public static List<string> GetOrderProvidersName(string path)
        {
            var directory = new DirectoryInfo(path);
            var listOfmdp = new List<string>();

            foreach (var file in directory.GetFiles("*.dll"))
            {
                try
                {
                    var assembly = Assembly.Load(AssemblyName.GetAssemblyName(file.FullName));
                    var Types = assembly.GetTypes();
                    foreach (var type in Types)
                    {
                        if (type.GetInterface("IDataProvider") == null && type.GetInterface("IOrderProvider") != null)
                        {
                            var attribute = Attribute.GetCustomAttribute(type, typeof(ProviderName)) as ProviderName;
                            listOfmdp.Add(attribute.Name);
                        }
                    }
                }
                catch (Exception ex)
                {
                    new RemotingLogClient().Trace(new FireMessageEventArgs(ex, DateTime.Now.TimeOfDay));
                }
            }

            return listOfmdp;
        }
        public static List<string> GetMixedProvidersName(string path)
        {
            var directory = new DirectoryInfo(path);
            var listOfmdp = new List<string>();

            foreach (var file in directory.GetFiles("*.dll"))
            {
                try
                {
                    var assembly = Assembly.Load(AssemblyName.GetAssemblyName(file.FullName));
                    var Types = assembly.GetTypes();
                    foreach (var type in Types)
                    {
                        if (type.GetInterface("IDataProvider") != null && type.GetInterface("IOrderProvider") != null)
                        {
                            var attribute = Attribute.GetCustomAttribute(type, typeof(ProviderName)) as ProviderName;
                            listOfmdp.Add(attribute.Name);
                        }
                    }
                }
                catch (Exception ex)
                {
                    new RemotingLogClient().Trace(new FireMessageEventArgs(ex, DateTime.Now.TimeOfDay));
                }
            }
            return listOfmdp;
        }
        public static List<string> GetFeesProvidersName(string path)
        {
            var directory = new DirectoryInfo(path);
            var listOfmdp = new List<string>();

            foreach (FileInfo file in directory.GetFiles("*.dll"))
            {
                try
                {
                    var assembly = Assembly.Load(AssemblyName.GetAssemblyName(file.FullName));
                    var Types = assembly.GetTypes();
                    foreach (var type in Types)
                    {
                        if (type.GetInterface("IFees") != null)
                        {
                            var attribute = Attribute.GetCustomAttribute(type, typeof(BrokerFees)) as BrokerFees;
                            listOfmdp.Add(attribute.Name);
                        }
                    }
                }
                catch (Exception ex)
                {
                    new RemotingLogClient().Trace(new FireMessageEventArgs(ex, DateTime.Now.TimeOfDay));
                }
            }
            return listOfmdp;
        }
    }
}